#include "sg_chart.h"
#include SG_MEM_INCLUDE


static void RefreshPart(sg_chart_t *obj, u8 type, u16 oldv);

sg_chart_t *SgChart_new()
{
    sg_chart_t *obj = SG_MEM_ALLOC(sizeof(sg_chart_t));
    if(obj == NULL)return NULL;
    memset(obj, 0, sizeof(sg_chart_t));
    obj->Width = 64;
    obj->Height = 64;
    obj->Border = 6;
    obj->PointSize = 4;
    obj->CurSize = 7;
    obj->BgColor = Lcd_GetColorHex(0x282b30);
    obj->GridColor = Lcd_GetColorHex(0x34373d);
    obj->MaxValue = 100;
    // obj->WaveNum = 0;
    // obj->ActiveWaveNum = 0;
    obj->PointNum = 10;
    // obj->Cur = 0;
    
    // 创建1个曲线
    SgChart_newWave(obj, Lcd_GetColorHex(0xDDDDDD));
    
    // SgChart_refreshAll(obj);
    return obj;
}

void SgChart_delete(sg_chart_t *obj)
{
    if(obj == NULL) return;
    while(obj->WaveNum > 0)
    {
        SgChart_DeleteLastWave(obj);
    }
    SG_MEM_FREE(obj);
}

/**
 * 创建一个波形曲线并将之添加到Chart进行显示。
 * @param obj sg_chart_t 对象
 * @param wave_color 曲线颜色
 * @return 曲线对象指针，其也会被保存在 sg_chart_t 的 Wave 列表中。
*/
sg_wave_t *SgChart_newWave(sg_chart_t *obj, lcd_color_t wave_color)
{
    if(obj->WaveNum >= 4)return NULL;
    sg_wave_t *wave = SG_MEM_ALLOC(sizeof(sg_wave_t));
    if(wave == NULL)return NULL;

    memset(wave, 0, sizeof(sg_wave_t));
    wave->Color = wave_color;
    wave->PointCoord = SG_MEM_ALLOC(sizeof(sg_coord_t) * obj->PointNum);
    wave->PointValue = SG_MEM_ALLOC(sizeof(u16) * obj->PointNum);
    memset(wave->PointValue, 0, sizeof(u16) * obj->PointNum);

    obj->Wave[obj->WaveNum] = wave;
    obj->WaveNum++;
    return wave;
}

/**
 * 删除 Chart 中最后添加的那个曲线（列表中最后一个）
 * @param obj sg_chart_t 对象
*/
void SgChart_DeleteLastWave(sg_chart_t *obj)
{
    if(obj->WaveNum > 0)
    {
        obj->WaveNum--;
        sg_wave_t *wave = obj->Wave[obj->WaveNum];
        SG_MEM_FREE(wave->PointValue);
        SG_MEM_FREE(wave->PointCoord);
        SG_MEM_FREE(wave);
    }
}

FORCE_IN_LINE void SgChart_setActiveWave(sg_chart_t *obj, u8 wave_num)
{
    obj->ActiveWaveNum = wave_num;
}

FORCE_IN_LINE void SgChart_setPosition(sg_chart_t *obj, sg_coord_t pos)
{
    obj->Pos = pos;
}

FORCE_IN_LINE void SgChart_setWidth(sg_chart_t *obj, u16 w)
{
    obj->Width = w;
}

FORCE_IN_LINE void SgChart_setHeight(sg_chart_t *obj, u16 height)
{
    obj->Height = height;
}

void SgChart_exeAction(sg_chart_t *obj, sg_act_t act)
{
    if(obj == NULL) return;
    sg_wave_t *act_wave = obj->Wave[obj->ActiveWaveNum];
    switch(act)
    {
    case SG_ACT_PLUS:
        if(act_wave->PointValue[obj->Cur] < obj->MaxValue)
        {
            act_wave->PointValue[obj->Cur]++;
            RefreshPart(obj, 1, 0);
        }
        break;
    case SG_ACT_MINUS:
        if(act_wave->PointValue[obj->Cur] > 0)
        {
            act_wave->PointValue[obj->Cur]--;
            RefreshPart(obj, 1, 0);
        }
        break;
    case SG_ACT_LEFT:
    {
        u16 old_cur = obj->Cur;
        if(obj->Cur <= 0)obj->Cur = obj->PointNum - 1;
        else obj->Cur--;
        RefreshPart(obj, 0, old_cur);
        break;
    }
    case SG_ACT_RIGHT:
    {
        u16 old_cur = obj->Cur;
        obj->Cur++;
        if(obj->Cur >= obj->PointNum)obj->Cur = 0;
        RefreshPart(obj, 0, old_cur);
        break;
    }
    default: break;
    }
}

void SgChart_refreshAll(sg_chart_t *obj)
{
    int i,j;
    u16 valid_x = obj->Pos.x + obj->Border;
    u16 valid_y = obj->Pos.y + obj->Border;
    u32 diff_y = (obj->Height - obj->Border * 2) * 100 / obj->MaxValue;    // 单位 0.01px

    if(obj == NULL) return;
    // 画背景
    Lcd_SetBgColor(obj->BgColor);
    Lcd_Clear(obj->Pos.x, obj->Pos.y, obj->Pos.x + obj->Width - 1, obj->Pos.y + obj->Height - 1);
    for(i = 0; i < 10; i++)
    {
        for(j = 0; j < obj->WaveNum; j++)
        {
            obj->Wave[j]->PointCoord[i].x = valid_x + i * ((obj->Width - obj->Border * 2) / 9);      // 点（和背景竖线）的X坐标
            obj->Wave[j]->PointCoord[i].y = valid_y + (obj->MaxValue - obj->Wave[j]->PointValue[i]) * diff_y / 100;  // 点的Y坐标
        }
        // 画背景竖线
        Lcd_SetPaintColor(obj->GridColor);
        Lcd_Fill(obj->Wave[0]->PointCoord[i].x, obj->Pos.y, obj->Wave[0]->PointCoord[i].x, obj->Pos.y + obj->Height - 1);
        // Lcd_Line(obj->PointCoord[i].x, obj->Pos.y, obj->PointCoord[i].x, obj->Pos.y + obj->Height - 1);    
        // 画点
        for(j = obj->WaveNum - 1; j >= 0; j--)
        {
            Lcd_SetPaintColor(obj->Wave[j]->Color);
            Lcd_Circle(obj->Wave[j]->PointCoord[i].x, obj->Wave[j]->PointCoord[i].y, obj->PointSize, true);
        }
    }
    // 画光标
    sg_wave_t *act_wave = obj->Wave[obj->ActiveWaveNum];
    Lcd_SetPaintColor(act_wave->Color);
    Lcd_Circle(act_wave->PointCoord[obj->Cur].x, act_wave->PointCoord[obj->Cur].y, obj->CurSize, true);
    // 画连接线
    for(i = 0; i < 9; i++)
    {
        for(j = obj->WaveNum - 1; j >= 0; j--)
        {
            Lcd_SetPaintColor(obj->Wave[j]->Color);
            Lcd_Line(obj->Wave[j]->PointCoord[i].x, obj->Wave[j]->PointCoord[i].y, obj->Wave[j]->PointCoord[i + 1].x, obj->Wave[j]->PointCoord[i + 1].y);
        }
    }
} //改成一条一条画完整曲线提升效率!!!!!!!!!!!!!!!!!!!!!!!!!!!

void SgChart_setCurValue(sg_chart_t *obj, u16 value)
{
    sg_wave_t *act_wave = obj->Wave[obj->ActiveWaveNum];

    if(obj->Cur >= obj->PointNum) obj->Cur = obj->PointNum - 1;
    act_wave->PointValue[obj->Cur] = value;
    RefreshPart(obj, 1, 0);
}

void SgChart_setCur(sg_chart_t *obj, u16 point_id)
{
    if(point_id >= obj->PointNum)point_id = obj->PointNum - 1;
    u16 old_cur = obj->Cur;
    obj->Cur = point_id;
    RefreshPart(obj, 0, old_cur);
}

/**
 * 局部刷新。
 * @param type 刷新类型，0：光标位置改变需要刷新；1：值改变需要刷新。
 * @param oldv 旧的光标位置，对于值改变的情况无意义
*/
static void RefreshPart(sg_chart_t *obj, u8 type, u16 oldv)
{
    u8 prev_cur;    // 上一个光标位置
    u16 valid_y = obj->Pos.y + obj->Border; // 顶部无效的 y 空间
    u32 diff_y = (obj->Height - obj->Border * 2) * 100 / obj->MaxValue;    // 一个值对应的y坐标距离，单位 0.01px
    sg_wave_t *act_wave = obj->Wave[obj->ActiveWaveNum];

    if(obj == NULL) return;

    if(type == 1) // 值改变需要刷新
    {
        prev_cur = obj->Cur;
        // 需要擦除连接线（用背景色画线）
        Lcd_SetPaintColor(obj->BgColor);
        if(obj->Cur > 0)    // 左侧有线
        {
            Lcd_Line(act_wave->PointCoord[obj->Cur-1].x, act_wave->PointCoord[obj->Cur-1].y, act_wave->PointCoord[obj->Cur].x, act_wave->PointCoord[obj->Cur].y);
        }
        if(obj->Cur < obj->PointNum - 1)    // 右侧有线
        {
            Lcd_Line(act_wave->PointCoord[obj->Cur].x, act_wave->PointCoord[obj->Cur].y, act_wave->PointCoord[obj->Cur+1].x, act_wave->PointCoord[obj->Cur+1].y);
        }
        // 擦除光标（用背景色画）
        // Lcd_SetPaintColor(obj->BgColor);
        Lcd_Circle(act_wave->PointCoord[prev_cur].x, act_wave->PointCoord[prev_cur].y, obj->CurSize, true);
        // 更新点的 Y 坐标
        act_wave->PointCoord[obj->Cur].y = valid_y + (obj->MaxValue - act_wave->PointValue[obj->Cur]) * diff_y / 100;  // 点的Y坐标
    }
    else    // 光标位置改变需要刷新
    {
        if(oldv >= obj->PointNum) return;
        prev_cur = oldv;
        // 擦除光标（用背景色画）
        Lcd_SetPaintColor(obj->BgColor);
        Lcd_Circle(act_wave->PointCoord[prev_cur].x, act_wave->PointCoord[prev_cur].y, obj->CurSize, true);
    }
    // 补齐背景线
    Lcd_SetPaintColor(obj->GridColor);
    Lcd_Fill(act_wave->PointCoord[prev_cur].x, obj->Pos.y, act_wave->PointCoord[prev_cur].x, obj->Pos.y + obj->Height - 1);
    // Lcd_Line(obj->PointCoord[prev_cur].x, obj->Pos.y, obj->PointCoord[prev_cur].x, obj->Pos.y + obj->Height - 1);
    // 画连接线（旧的或者新的）
    if(prev_cur > 0)  // 左侧有线
    {
        int j;
        for(j = obj->WaveNum - 1; j >= 0; j--)
        {
            Lcd_SetPaintColor(obj->Wave[j]->Color);
            Lcd_Line(obj->Wave[j]->PointCoord[prev_cur-1].x, obj->Wave[j]->PointCoord[prev_cur-1].y, obj->Wave[j]->PointCoord[prev_cur].x, obj->Wave[j]->PointCoord[prev_cur].y);
        }
    }
    if(prev_cur < obj->PointNum - 1) // 右侧有线
    {
        int j;
        for(j = obj->WaveNum - 1; j >= 0; j--)
        {
            Lcd_SetPaintColor(obj->Wave[j]->Color);
            Lcd_Line(obj->Wave[j]->PointCoord[prev_cur].x, obj->Wave[j]->PointCoord[prev_cur].y, obj->Wave[j]->PointCoord[prev_cur+1].x, obj->Wave[j]->PointCoord[prev_cur+1].y);
        }
    }
    // 画点
    Lcd_SetPaintColor(act_wave->Color);
    if(type == 0)   // 光标位置改变，需要画点在原来光标的位置
    {
        int j;
        for(j = obj->WaveNum - 1; j >= 0; j--)
        {
            Lcd_SetPaintColor(obj->Wave[j]->Color);
            Lcd_Circle(obj->Wave[j]->PointCoord[prev_cur].x, obj->Wave[j]->PointCoord[prev_cur].y, obj->PointSize, true);
        }
    }
    else    // 值改变
    {
        if(obj->Cur > 0)  // 左侧点有线被擦除，需要重新画点
        {
            int j;
            for(j = obj->WaveNum - 1; j >= 0; j--)
            {
                Lcd_SetPaintColor(obj->Wave[j]->Color);
                Lcd_Circle(obj->Wave[j]->PointCoord[obj->Cur-1].x, obj->Wave[j]->PointCoord[obj->Cur-1].y, obj->PointSize, true);
            }
        }
        if(obj->Cur < obj->PointNum - 1) // 右侧点有线被擦除，需要重新画点
        {
            int j;
            for(j = obj->WaveNum - 1; j >= 0; j--)
            {
                Lcd_SetPaintColor(obj->Wave[j]->Color);
                Lcd_Circle(obj->Wave[j]->PointCoord[obj->Cur+1].x, obj->Wave[j]->PointCoord[obj->Cur+1].y, obj->PointSize, true);
            }
        }
        // 其他波形在该位置的点可能被擦除，需要重新画点
        int j;
        for(j = obj->WaveNum - 1; j >= 0; j--)
        {
            Lcd_SetPaintColor(obj->Wave[j]->Color);
            Lcd_Circle(obj->Wave[j]->PointCoord[obj->Cur].x, obj->Wave[j]->PointCoord[obj->Cur].y, obj->PointSize, true);
        }
    }
    // 画新光标
    Lcd_SetPaintColor(act_wave->Color);
    Lcd_Circle(act_wave->PointCoord[obj->Cur].x, act_wave->PointCoord[obj->Cur].y, obj->CurSize, true);
}







